package com.ncmmall.application.business.live;

import com.feijin.commons.lang.Requires;
import com.feijin.commons.webs.SyncLock;
import com.ncmmall.domain.business.live.LiveAccountRemove;
import com.ncmmall.domain.business.live.LiveAccountRemoveRepository;
import com.ncmmall.domain.business.live.LiveCheck;
import com.ncmmall.domain.business.live.LiveCheckRepository;
import com.ncmmall.domain.business.live.LiveFans;
import com.ncmmall.domain.business.live.LiveFansRepository;
import com.ncmmall.domain.business.live.LiveFeedback;
import com.ncmmall.domain.business.live.LiveFeedbackRepository;
import com.ncmmall.domain.business.live.LiveGoods;
import com.ncmmall.domain.business.live.LiveGoodsAnchor;
import com.ncmmall.domain.business.live.LiveGoodsAnchorRepository;
import com.ncmmall.domain.business.live.LiveSessionGoods;
import com.ncmmall.domain.business.live.LiveSessionGoodsRepository;
import com.ncmmall.domain.business.live.LiveWithdrawRepository;
import com.ncmmall.domain.business.live.QLiveFans;
import com.ncmmall.domain.business.live.QLiveGoods;
import com.ncmmall.domain.business.live.QLiveGoodsAnchor;
import com.ncmmall.domain.security.role.QRole;
import com.ncmmall.domain.security.role.Role;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.domain.security.user.WebUserRepository;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 直播业务
 *
 * @author Samuel
 * @date 2020-09-02 15:43
 */
@Service
@Transactional
@RequiredArgsConstructor
public class LiveApplication {

    private final QueryChannelService queryChannelService;
    private final WebUserRepository userRepository;
    private final LiveCheckRepository liveCheckRepository;
    private final LiveSessionGoodsRepository liveSessionGoodsRepository;
    private final LiveFansRepository liveFansRepository;
    private final LiveAccountRemoveRepository liveAccountRemoveRepository;
    private final LiveFeedbackRepository liveFeedbackRepository;
    private final LiveGoodsAnchorRepository liveGoodsAnchorRepository;
    private final LiveWithdrawRepository liveWithdrawRepository;

    /**
     * 检查用户是否是主播
     */
    public static boolean checkUserIsAnchor(WebUser user) {
        return user.getLiveType() == 1;
    }

    /**
     * 检查用户是否是助理
     */
    public static boolean checkUserIsAssistant(WebUser user) {
        return user.getLiveType() == 2;
    }

    /**
     * 检查用户必须是主播
     */
    public static void requireUserIsAnchor(WebUser user) {
        if (!checkUserIsAnchor(user)) {
            throw new IllegalArgumentException("当前用户不是主播");
        }
    }

    /**
     * 检查用户必须是主播
     */
    public static void requireUserIsAnchor(WebUser user, String message) {
        if (!checkUserIsAnchor(user)) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * 检查用户必须是主播助理
     */
    public static void requireUserIsAssistant(WebUser user) {
        if (!checkUserIsAssistant(user)) {
            throw new IllegalArgumentException("当前用户不是主播助理");
        }
    }

    /**
     * 主播申请
     */
    public void apply(LiveCheck params) {

        Requires.notNull(params.getUser(), "用户不存在");
        Requires.isTrue(params.getUser().getLiveType() != 1, "当前用户已经是主播，无法申请");
        Requires.isTrue(params.getUser().getLiveType() != 2, "当前用户已经是主播助理，无法申请");

        synchronized (SyncLock.getLock(String.valueOf(params.getUser().getId()))) {

            int count = queryChannelService.selectCount("select count(*) from live_check where user_id = :uid and checkStatus = 1",
                    ImmutableMap.of("uid", params.getUser().getId()));
            Requires.isTrue(count == 0, "已提交申请，请不要重复申请");

            Requires.hasLength(params.getName(), "请输入直播间名称");
            Requires.hasLength(params.getIntroduce(), "请输入直播间介绍");
            Requires.hasLength(params.getImage(), "请上传直播间图片");
            Requires.hasLength(params.getIdCardNo(), "请输入身份证号码");
            Requires.hasLength(params.getIdCardFront(), "请上传身份证正面照片");
            Requires.hasLength(params.getIdCardReverse(), "请上传身份证反面照片");

            count = queryChannelService.selectCount("select count(*) from live_check where name = :name and (checkStatus = 1 or checkStatus = 2)",
                    ImmutableMap.of("name", params.getName()));
            Requires.isTrue(count == 0, "该直播间名称被注册");

            count = queryChannelService.selectCount("select count(*) from live_check where idCardNo = :idCardNo and (checkStatus = 1 or checkStatus = 2)",
                    ImmutableMap.of("idCardNo", params.getIdCardNo()));
            Requires.isTrue(count == 0, "该身份证号码已被注册");

            params.setCreateTime(new Timestamp(System.currentTimeMillis()));
            params.setCheckStatus(1);
            liveCheckRepository.save(params);
        }
    }

    /**
     * 主播审核
     */
    public void check(LiveCheck liveCheck, int status, String note) {

        Requires.isTrue(status == 2 || status == 3, "审核状态不正确");
        liveCheck.setCheckStatus(status);
        liveCheck.setCheckNote(note);
        liveCheck.setCheckTime(new Timestamp(System.currentTimeMillis()));
        liveCheckRepository.save(liveCheck);

        if (liveCheck.getCheckStatus() == 2) {
            //审核通过设置用户直播信息
            WebUser user = liveCheck.getUser();
            user.setLiveType(1);
            user.setLiveName(liveCheck.getName());
            user.setLiveIntroduce(liveCheck.getIntroduce());
            user.setLiveImage(liveCheck.getImage());
            user.setLiveIdCardNo(liveCheck.getIdCardNo());
            user.setLiveIdCardFront(liveCheck.getIdCardFront());
            user.setLiveIdCardReverse(liveCheck.getIdCardReverse());
            user.setLiveID(generateLiveID());
            user.setLiveCreateTime(new Timestamp(System.currentTimeMillis()));

            Role role = queryChannelService.findOne(QRole.role.name.eq("ANCHOR"), Role.class);
            user.setRole(role);
            userRepository.save(user);

            unlockAssistant(user, false);

            //当前设为全部直播间的商品池，设置给该主播
            List<LiveGoods> liveGoodsList = queryChannelService.findAll(QLiveGoods.liveGoods.status.eq(2).and(QLiveGoods.liveGoods.liveScope.eq(1)), LiveGoods.class);
            for (LiveGoods liveGoods : liveGoodsList) {
                int count = queryChannelService.selectCount("select count(*) from live_goods_anchor where live_goods_id = :gid and anchor_id = :aid",
                        ImmutableMap.of("gid", liveGoods.getId(), "aid", user.getId()));
                if (count == 0) {
                    LiveGoodsAnchor liveGoodsAnchor = new LiveGoodsAnchor();
                    liveGoodsAnchor.setLiveGoods(liveGoods);
                    liveGoodsAnchor.setAnchor(user);
                    liveGoodsAnchor.setGoods(liveGoods.getGoods());
                    liveGoodsAnchorRepository.save(liveGoodsAnchor);
                }
            }
        }
    }

    private void unlockAssistant(WebUser anchor, boolean lock) {
        List<WebUser> users = queryChannelService.findAll(QWebUser.webUser.liveType.eq(2).and(QWebUser.webUser.anchor.id.eq(anchor.getId())), WebUser.class);
        for (WebUser webUser : users) {
            webUser.setAccountNonLocked(!lock);
        }
        userRepository.save(users);
    }

    /**
     * 主播批量审核
     */
    public void check(String checkIds, int status, String note) {
        List<Long> ids = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(checkIds).stream().map(Long::parseLong).collect(Collectors.toList());
        for (Long id : ids) {
            LiveCheck liveCheck = liveCheckRepository.findOne(id);
            if (liveCheck != null) {
                check(liveCheck, status, note);
            }
        }
    }

    private String generateLiveID() {
        String liveID = RandomStringUtils.randomNumeric(8);
        while (queryChannelService.selectCount("select count(*) from security_web_user where liveID = :id", ImmutableMap.of("id", liveID)) != 0) {
            liveID = RandomStringUtils.randomNumeric(8);
        }
        return liveID;
    }

    public void save(WebUser user) {
        userRepository.save(user);
    }

    /**
     * 删除直播间
     */
    public void removeAchor(WebUser anchor) {
        anchor.setLiveType(0);
        anchor.setRole(queryChannelService.findOne(QRole.role.name.eq("MEMBER"), Role.class));
        userRepository.save(anchor);

        unlockAssistant(anchor, true);
    }


    /**
     * 添加代播商品池商品到我的代播商品
     */
    public void addGoodsManager(WebUser anchor, String ids) {

        Set<Long> list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(ids).stream().map(Long::valueOf).collect(Collectors.toSet());
        List<LiveGoodsAnchor> goodsAnchorList = queryChannelService.findAll(QLiveGoodsAnchor.liveGoodsAnchor.id.in(list).and(QLiveGoodsAnchor.liveGoodsAnchor.anchor.id.eq(anchor.getId())), LiveGoodsAnchor.class);

        goodsAnchorList.removeIf(g -> queryChannelService.selectCount("select count(*) from live_session_goods where anchor_id = :aid and live_session_id is null and live_goods_anchor_id = :gaid",
                ImmutableMap.of("aid", anchor.getId(), "gaid", g.getId())) > 0);

        for (LiveGoodsAnchor goodsAnchor : goodsAnchorList) {
            LiveSessionGoods sessionGoods = new LiveSessionGoods();
            sessionGoods.setAnchor(anchor);
            sessionGoods.setLiveGoodsAnchor(goodsAnchor);
            sessionGoods.setGoods(goodsAnchor.getGoods());
            liveSessionGoodsRepository.save(sessionGoods);
        }

    }

    /**
     * 关注直播/取消关注主播，返回最终关注状态
     *
     * @param anchor 主播
     * @param user   用户
     * @return 最终的关注状态 true关注 false未关注
     */
    public boolean attentionAnchor(WebUser anchor, WebUser user) {

        LiveApplication.requireUserIsAnchor(anchor, "主播id不正确");
        Requires.isTrue(anchor.getId() != user.getId(), "不能关注自己");

        LiveFans liveFans = queryChannelService.findOne(QLiveFans.liveFans.anchor.id.eq(anchor.getId()).and(QLiveFans.liveFans.fans.id.eq(user.getId())), LiveFans.class);
        if (liveFans != null) {
            liveFansRepository.delete(liveFans);
            return false;
        }

        liveFans = new LiveFans();
        liveFans.setAnchor(anchor);
        liveFans.setFans(user);
        liveFans.setCreateTime(new Timestamp(System.currentTimeMillis()));
        liveFansRepository.save(liveFans);
        return true;
    }


    /**
     * 主播注销账号
     */
    public void closeAccount(LiveAccountRemove liveAccountRemove) {
        liveAccountRemove.setId(0);
        liveAccountRemove.setCreateTime(new Timestamp(System.currentTimeMillis()));
        liveAccountRemoveRepository.save(liveAccountRemove);

        WebUser user = liveAccountRemove.getUser();
        removeAchor(user);
    }

    /**
     * 直播反馈
     */
    public void feedback(LiveFeedback feedback) {
        feedback.setCreateTime(new Timestamp(System.currentTimeMillis()));
        liveFeedbackRepository.save(feedback);
    }

    /**
     * 保存直播商品红包
     */
    public void saveSessionGoods(LiveSessionGoods sessionGoods) {
        liveSessionGoodsRepository.save(sessionGoods);
    }




}
